package com.warm.mini.wework.util;

import com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler;
import lombok.extern.slf4j.Slf4j;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Description xml 处理
 * @Author warmchuang
 * @Date 2022/2/9 15:34
 */
@Slf4j
public class JaxbUtil {

    public static Map<Class<?>, JAXBContext> contextMap = new ConcurrentHashMap<>();

    public static <T> T xml2Bean(String xml, Class<T> c) {
        T t = null;
        StringReader reader = null;
        try {
            JAXBContext context = getContext(c);
            Unmarshaller unmarshaller = context.createUnmarshaller();
            reader = new StringReader(xml);
            t = (T) unmarshaller.unmarshal(reader);
        } catch (Exception e) {
            log.info("error:{}", e.getMessage(), e);
        } finally {
            if (reader != null) {
                reader.close();
            }
        }

        return t;
    }

    public static String bean2Xml(Object source) {
        StringWriter writer = null;
        try {
            JAXBContext jaxbContext = JAXBContext.newInstance(source.getClass());
            Marshaller marshaller = jaxbContext.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
            marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
            marshaller.setProperty(CharacterEscapeHandler.class.getName(), (CharacterEscapeHandler) (ch, start, length, isAttVal, writer1) -> writer1.write(ch, start, length));
            writer = new StringWriter();
            marshaller.marshal(source, writer);
            return writer.toString();
        } catch (JAXBException e) {
            log.info("error:{}", e.getMessage(), e);
        } finally {
            if (writer != null) {
                try {
                    writer.close();
                } catch (Exception e) {
                    log.info("error:{}", e.getMessage(), e);
                }
            }
        }
        return null;
    }

    private static JAXBContext getContext(Class<?> clazz) throws JAXBException {
        JAXBContext context = contextMap.get(clazz);
        if (context == null) {
            context = JAXBContext.newInstance(clazz);
            contextMap.put(clazz, context);
        }
        return context;
    }
}
